home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.001
/
crossfir~
/
eutl
/
arglist
/
arglist.c
next >
Wrap
C/C++ Source or Header
|
1994-10-28
|
7KB
|
370 lines
#include <arglist.h>
#include <dynarray.h>
#include <xmalloc.h>
#include <libc.h>
char *arglist_packagever = "ArgList V1.0";
char *arglist_Eoutofbounds = "Argument out of bounds";
char *arglist_Etypemismatch = "Requested argument of wrong type";
char *arglist_Eunpackerror = "Error while unpacking";
static ErrorFunction Erf = LongJmpErrorFunction;
enum ArgType { Long=0, String=1, Buffer=2, Char=3 };
static char *typetostring(int type)
{
switch(type) {
case Long: return "Long";
break;
case String: return "String";
break;
case Buffer: return "Buffer";
break;
case Char: return "Char";
break;
default: return "Unknown Type\n";
}
}
struct Arg {
enum ArgType type;
union {
char c;
long l;
unsigned long ul;
char *s;
struct {
void *b;
unsigned long size;
} b;
} u;
};
struct __ArgList {
DynArray a;
int size;
};
ArgList ArgList_create()
{
ArgList ret;
ret = xmalloc(sizeof(struct __ArgList));
ret->a = dyn_create(sizeof(struct Arg),0,10);
ret->size = 0;
return ret;
}
void ArgList_destroy(ArgList gone)
{
int i;
struct Arg *a;
for(i=0;i<gone->size;i++) {
a = dyn_get(gone->a,i);
switch (a->type) {
case String: free(a->u.s);
break;
case Buffer: free(a->u.b.b);
break;
default:
}
}
dyn_destroy(gone->a);
free(gone);
}
void ArgList_addLong(ArgList to,long val)
{
struct Arg a;
a.type = Long;
a.u.l = val;
dyn_set(to->a,to->size,&a);
to->size++;
}
void ArgList_addChar(ArgList to,char val)
{
struct Arg a;
a.type = Char;
a.u.c = val;
dyn_set(to->a,to->size,&a);
to->size++;
}
void ArgList_addString(ArgList to,char *val)
{
struct Arg a;
a.type = String;
a.u.s = xmalloc(strlen(val)+1);
strcpy(a.u.s,val);
dyn_set(to->a,to->size,&a);
to->size++;
}
void ArgList_addBuf(ArgList to,void *buf,unsigned long len)
{
struct Arg a;
a.type = Buffer;
a.u.b.b = xmalloc(len);
bcopy(buf,a.u.b.b,len);
a.u.b.size = len;
dyn_set(to->a,to->size,&a);
to->size++;
}
struct Arg *get(ArgList from,int posn)
{
return (struct Arg *)dyn_get(from->a,posn);
}
char ArgList_getChar(ArgList from,int posn)
{
struct Arg *a;
a = get(from,posn);
if (a->type != Char)
Erf(arglist_packagever,arglist_Etypemismatch,
"Type mismatch, expected char, got %s",typetostring(a->type));
return a->u.c;
}
long ArgList_getLong(ArgList from,int posn)
{
struct Arg *a;
a = get(from,posn);
if (a->type != Long)
Erf(arglist_packagever,arglist_Etypemismatch,
"Type mismatch, expected long, got %s",typetostring(a->type));
return a->u.l;
}
char *ArgList_getString(ArgList from,int posn)
{
struct Arg *a;
a = get(from,posn);
if (a->type != String)
Erf(arglist_packagever,arglist_Etypemismatch,
"Type mismatch, expected string, got %s",typetostring(a->type));
return a->u.s;
}
void *ArgList_getBuf(ArgList from,int posn,unsigned long *len)
{
struct Arg *a;
a = get(from,posn);
if (a->type != Buffer)
Erf(arglist_packagever,arglist_Etypemismatch,
"Type mismatch, expected buffer, got %s",typetostring(a->type));
if (len!=NULL)
*len = a->u.b.size;
return a->u.b.b;
}
int ArgList_getLength(ArgList from)
{
return from->size;
}
unsigned char *packlong(unsigned char *to,long v)
{
if (sizeof(long)>4) {
int thirtyone = 31;
if (v < -((1<<thirtyone) - 1) || v > ((1<<thirtyone) - 1))
Erf(arglist_packagever,arglist_Eoutofbounds,
"Tried to send a long which is larger than 4 bytes.\n");
}
if (v<0) {
v = -v;
*to = (v >> 24);
*to |= 128;
} else {
*to = (v >> 24);
}
to++;
*to = (v >> 16) & 0xff;
to++;
*to = (v >> 8) & 0xff;
to++;
*to = v & 0xff;
to++;
return to;
}
unsigned char *unpacklong(unsigned char *from,long *v)
{
int lt0;
lt0 = *from & 128;
*v = *from & 0x7f;
from++;
*v = (*v << 8) | *from;
from++;
*v = (*v << 8) | *from;
from++;
*v = (*v << 8) | *from;
from++;
if (lt0)
*v = - *v;
return from;
}
unsigned char *packstring(unsigned char *to,char *s)
{
long len = strlen(s);
to = packlong(to,len);
bcopy(s,to,len);
return to+len;
}
unsigned char *unpackstring(unsigned char *from,char **s)
{
long len;
from = unpacklong(from,&len);
*s = xmalloc(len+1);
bcopy(from,*s,len);
(*s)[len] = '\0';
return from+len;
}
unsigned char *packbuffer(unsigned char *to,void *b,unsigned long size)
{
to = packlong(to,size);
bcopy(b,to,size);
return to+size;
}
unsigned char *unpackbuffer(unsigned char *from,void **b,unsigned long *size)
{
from = unpacklong(from,size);
*b = xmalloc(*size);
bcopy(from,*b,*size);
return from + *size;
}
void *ArgList_pack(ArgList from,unsigned long *osize)
{
int i;
unsigned long size;
unsigned char *ret,*t;
struct Arg *a;
size = 4; /* number of entries in argument list */
for(i=0;i<from->size;i++) {
a = dyn_get(from->a,i);
size++; /* type of what is being passed */
switch(a->type) {
case Long: size += 4;
break;
case String: size += strlen(a->u.s) + 4;
break;
case Buffer: size += a->u.b.size + 4;
break;
case Char: size += 1;
break;
default:
Erf(arglist_packagever,internal_Einternal,
"Bad type(%d) for arglist entry\n",a->type);
}
}
ret = xmalloc(size);
*osize = size;
t = packlong(ret,from->size);
for(i=0;i<from->size;i++) {
a = dyn_get(from->a,i);
*t = (char)(a->type);
t++;
switch(a->type) {
case Long: t = packlong(t,a->u.l);
break;
case String: t = packstring(t,a->u.s);
break;
case Buffer: t = packbuffer(t,a->u.b.b,a->u.b.size);
break;
case Char: *t = a->u.c;t++;
break;
}
}
return ret;
}
ArgList ArgList_unpack(void *ifrom,unsigned long size)
{
unsigned char *from = ifrom;
unsigned char *end = from + size;
int type;
long nents,i;
ArgList ret;
struct Arg a;
from = unpacklong(from,&nents);
if (nents>size)
Erf(arglist_packagever,arglist_Eunpackerror,
"Can't possibly have more entries(%d) than the size(%d)\n",
nents,size);
ret = xmalloc(sizeof(struct __ArgList));
ret->a = dyn_create(sizeof(struct Arg),nents,10);
ret->size = nents;
for(i=0;i<nents;i++) {
type = *from;
from++;
switch(type) {
case Long:
from = unpacklong(from,&a.u.l);
break;
case String:
from = unpackstring(from,&a.u.s);
break;
case Buffer:
from = unpackbuffer(from,&a.u.b.b,&a.u.b.size);
break;
case Char:
a.u.c = *from;from++;
break;
default:
Erf(arglist_packagever,arglist_Eunpackerror,
"Invalid type(%d) while unpacking\n",type);
}
if (from>end) {
Erf(arglist_packagever,arglist_Eunpackerror,
"More stuff specified in arglist than space given by size\n");
}
a.type = type;
dyn_set(ret->a,i,&a);
}
return ret;
}
void ArgList_send(TcpSocket to,ArgList val)
{
void *buf;
unsigned long size;
buf = ArgList_pack(val,&size);
SendSizedMsg(to,buf,size);
free(buf);
}
ArgList ArgList_receive(TcpSocket from)
{
ArgList ret;
void *buf;
long size;
buf = GetSizedMsg(from,&size);
ret = ArgList_unpack(buf,size);
return ret;
}